package edos.prm.metrics;

import edos.prm.activity.Operation;
import edos.prm.artifact.Artifact;
import edos.prm.artifact.Attribute;
import edos.prm.util.Time;

/**
 * A {@code Metric} represents a measure of process resources.
 * <p> 
 * A {@code Metric} can represent a key performance indicator of a project, or
 * generally indicate the status of process execution.
 * 
 * @version 1.0
 */
public interface Metric extends Artifact {

	/**
	 * Return the metric expression of the metric that gets evaluated.
	 * 
	 * @return the metric's {@code MetricExpression}
	 */
	public MetricExpression getMetricExpression();
	
	/**
	 * Indicates the purpose of this metric.
	 * <p>
	 * The viewpoint indicates the project, its topics and its activities that
	 * are influenced by a metric.
	 * 
	 * @return a MetrivViewpoint for this metric.
	 */
	@Attribute
	public MetricViewpoint getViewpoint();

	/**
	 * Returns the moment from when this metric is active.
	 * 
	 * @return the time of activation for this metric.
	 */
	public Time getValidityStart();

	/**
	 * Indicates the moment when this metric is no longer active.
	 * 
	 * @return the time of dismantlement for this metric.
	 */
	public Time getValidityEnd();

	/**
	 * Gives a description of this metric
	 * 
	 * @return a text describing this metric
	 */
	public String getDescription();

	/**
	 * Returns the name of this metric
	 * 
	 * @return a String name for this metric
	 */
	public String getName();

	/**
	 * An {@code Operational} metric is bound to an {@code Operation}.
	 * <p>
	 * The execution of the operation provokes evaluation of the associated
	 * metric.
	 */
	public interface OperationalMetric extends Metric {
		/**
		 * Returns the operation that this metric measures.
		 * 
		 * @return an {@code Operation} bound to this metric.
		 */
		public Operation getOperation(); 
	}
	
	/**
	 * An {@code OnDemandMetric} is a metric that is evaluated on the explicit
	 * demand of the {@code MetricManager} activity.
	 */
	public interface OnDemandMetric extends Metric {}

	/**
	 * Default Java implementation of the {@code Metric} interface.
	 */
	abstract class PrmMetric implements Metric {

		private String description;
		private String name;
		private MetricViewpoint viewPoints;
		private Time start, end;
		private MetricExpression expression;

		PrmMetric(String description, String name, MetricViewpoint viewPoints,
				Time start, Time end, MetricExpression expression) {
			this.description = description;
			this.name = name;
			this.viewPoints = viewPoints;
			this.start = start;
			this.end = end;
			this.expression = expression;
		}

		public String getDescription() {
			return this.description;
		}

		public String getName() {
			return this.name;
		}

		public Time getValidityEnd() {
			return end;
		}

		public Time getValidityStart() {
			return start;
		}

		public MetricViewpoint getViewpoint() {
			return this.viewPoints;
		}
		
		public MetricExpression getMetricExpression() {
			return this.expression;
		}
	}
	
	/**
	 * Default Java implementation of an operational metric.
	 */
	class PrmOperationalMetric extends PrmMetric implements OperationalMetric {
		
		private Operation operation;
		
		public PrmOperationalMetric(String description, String name,
				MetricViewpoint viewPoints, Time start, Time end,
				MetricExpression expression, Operation operation) {
			super(description, name, viewPoints, start, end, expression);
			this.operation = operation;
		}
		
		public Operation getOperation() {
			return operation;
		}
	}
	
	/**
	 * Default Java implementation of an operational metric.
	 */
	class PrmOnDemandMetric extends PrmMetric implements OnDemandMetric {
		PrmOnDemandMetric(String description, String name,
				MetricViewpoint viewPoints, Time start, Time end,
				MetricExpression expression) {
			super(description, name, viewPoints, start, end, expression);
		}}
}
